let net = require('net');
const Frame = require("./net/Frame")
const Server = require("./Server")
const MD5 = require("./md5")
const log4js = require("log4js");
const Log = log4js.getLogger("master");
/**
 * Master 就是一个 Socket 服务端，
 * 用来管理 Server
 * 只和 Proxy 通信，将 Proxy 发送的消息交给对应的 Server。
 * （ server 根据消息中的 cid ，将消息数据发给真实 Client ）
 *
 */

class Master {
    constructor(port, password){
        this.port = port;
        this.password = MD5(MD5(password));
        // 存储所有需要管理的服务器
        // 代理与服务器的映射关系 一一映射
        this.servers = {}
    }

    // 如果端口已经被占用则快速失败
    checkPortIsUsed(port){
        for (let key in this.servers){
            if( this.servers[key] && port == this.servers[key].port ){
                return true;
            }
        }
        return false;
    }

    async createServer(proxy, frame, port){
        try{
            if( this.checkPortIsUsed(port) ){
                return false;
            }
            let server = new Server(frame, port);
            await server.start();
            this.servers[proxy] = server;
            return true;
        }catch (e){
            return false;
        }
    }

    async execute(proxy, frame, cmd, data){
        switch (cmd){
            case "reg" :
                Log.debug(proxy + " reg " + data.port)
                if( this.password == data.password ){
                    let ret = await this.createServer(proxy, frame, data.port)
                    if( ret ){
                        frame.send({
                            cmd : "ready"
                        })
                    }else{
                        frame.send({
                            cmd : "error",
                            data : "注册端口 " + data.port + " 失败"
                        })
                    }
                }else{
                    frame.send({
                        cmd : 'error',
                        data : '口令错误'
                    });
                }
                break;

            case "data" : {
                Log.debug(proxy + " has data ")
                let server = this.servers[proxy]
                if( server ){
                    server.distribute(data)
                }
                break;
            }
            case "delete" : {
                Log.debug(proxy + " has delete ")
                let server = this.servers[proxy]
                if( server ){
                    server.control(data)
                }
                break;
            }
            case "unreg" : {
                Log.debug(proxy + " unreg ")
                let server = this.servers[proxy]
                if( server ){
                    server.destroy();
                    delete this.servers[proxy]
                }
                break;
            }
            default:
                frame.send({
                    cmd : 'error',
                    data : "未知的命令 " + cmd
                });
                break;
        }
    }

    start(){
        let server = net.createServer((sock) => {

            let proxy = sock.remoteAddress + ' ' + sock.remotePort;
            let frame = new Frame(proxy, sock);

            Log.debug('PROXY 接入: ' + proxy);

            frame.onRequest( (data) => {
                this.execute(proxy, frame, data.cmd, data.data)
            });

            frame.onResponse( (data) => {
                this.execute(proxy, frame, data.cmd, data.data)
            });

            frame.onError( (error) => {
                Log.debug(error + ' PROXY ' + proxy);
                this.execute(proxy, 0, 'unreg');
            })
        })

        server.on('error', function (e) {
            Log.error(e);
        })

        server.listen(this.port,  () => {
            Log.info('Master listening on 0.0.0.0:' + this.port);
        });
    }
}


module.exports = Master;